package org.example.designmodel.future;

import com.google.common.util.concurrent.*;
import org.example.utils.LogUtils;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class GoogleGuavaTest {

    private static final int TLEEP_CAP = 2000;

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        DrinkTea drinkTea = new DrinkTea();

        // java线程池
        ExecutorService service = Executors.newFixedThreadPool(10);

        // guava线程池
        ListeningExecutorService jPool = MoreExecutors.listeningDecorator(service);

        ListenableFuture<Boolean> hotWaterFuture = jPool.submit(new HotWater());

        Futures.addCallback(hotWaterFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                if (result) {
                    drinkTea.hotWater = true;
                    drinkTea.drinkTea();
                }
            }

            @Override
            public void onFailure(Throwable throwable) {
                LogUtils.info("烧水失败，没有茶喝");
            }
        });

        ListenableFuture<Boolean> washCupFuture = jPool.submit(new WashCup());
        Futures.addCallback(washCupFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                System.out.println("onSuccess : " + result);
                if (result) {
                    drinkTea.washCup = true;
                    drinkTea.drinkTea();
                }
            }

            @Override
            public void onFailure(Throwable throwable) {
                LogUtils.info("洗茶壶，没有茶喝");
            }
        });

        hotWaterFuture.get();
        washCupFuture.get();

        LogUtils.info("先干其他的事情");
        Thread.sleep(TLEEP_CAP);
        LogUtils.info("执行完成");
    }

    static class DrinkTea {
        public boolean hotWater;
        public boolean washCup;

        public DrinkTea() {

        }

        public void drinkTea() {
            if (hotWater && washCup) {
                LogUtils.info("泡茶喝");
            } else if (hotWater) {
                LogUtils.info("水烧开了，没有茶壶");
            } else if (washCup) {
                LogUtils.info("茶壶洗干净了，但是烧水失败了");
            }
        }
    }

    /**
     * 烧水线程
     */
    static class HotWater implements Callable<Boolean> {
        @Override
        public Boolean call() throws Exception {
            try {
                LogUtils.info("洗好水壶");
                LogUtils.info("灌上凉水");
                LogUtils.info("放在火上");
                Thread.sleep(TLEEP_CAP);
                LogUtils.info("水开了");
                return true;
            } catch (InterruptedException e) {
                LogUtils.info("烧水报错了");
                return false;
            }
        }
    }

    static class WashCup implements Callable<Boolean> {
        @Override
        public Boolean call() throws Exception {
            try {
                LogUtils.info("洗茶壶");
                LogUtils.info("洗茶杯");
                LogUtils.info("拿茶叶");
                Thread.sleep(TLEEP_CAP);
                LogUtils.info("洗完了");
                throw new Exception("洗茶壶异常");
//                return true;
            } catch (InterruptedException e) {
                LogUtils.info("洗茶壶失败了");
                return false;
            }
        }
    }
}
